package MapperModule

import (
	"database/sql"
	"fmt"
	"gdbc/gdbc"
	"strconv"
	"reflect"
	"unsafe"
	"errors"
)

func QUERY_TEMPLATE(mappermodule MapperModule, method string, param interface{}) ([]map[string]interface{}, error) {
	var dbAnTxInterface DbAnTxInterface
	var stmt *sql.Stmt
	var err error
	//fmt.Println(mappermodule.BeginTx)
	if (mappermodule.BeginTx) {
		//事务已开启，说明已有db
		dbAnTxInterface = mappermodule.TX
		var txaddr = fmt.Sprintf("%p", unsafe.Pointer(mappermodule.TX))
		logger.Debug("已开启事务，事务管理器[" + txaddr + "]，事务ID为[" + strconv.Itoa(int(mappermodule.TXID)) + "]")
	} else {
		dbAnTxInterface = gdbc.GetDB(mappermodule.GdbcName)
	}

	//加载Mapper文件信息
	var execsql, _ = getExecSql(mappermodule, method,param)

	//解析参数与Mapper映射关系
	var args []interface{}
	execsql,args,err = parseParameter(execsql,param)
	if err != nil {
		logger.Error("解析参数错误[" + err.Error() + "]")
		return nil, err
	}

	//预编译SQL
	stmt, err = dbAnTxInterface.Prepare(execsql)
	if (err != nil) {
		logger.Error("预编译sql错误错误信息为[" + err.Error() + "]")
		return nil, errors.New("预编译sql错误错误信息为[" + err.Error() + "]")
	}
	defer stmt.Close()

	//执行SQL
	var result = make([]map[string]interface{}, 0, 1)
	rows, err := stmt.Query(args...)
	if err != nil {
		logger.Error("SQL查询错误[" + err.Error() + "]")
		return nil, err
	}
	for (rows.Next()) {
		columns, _ := rows.Columns()
		columnTypes, _ := rows.ColumnTypes()
		scanType := make([]reflect.Type, 0, 10)
		for _, ct := range columnTypes {

			scanType = append(scanType, ct.ScanType())
		}
		//fmt.Println(scanType)
		scannerdest := CreateScanerDest(columns, scanType)
		rows.Scan(scannerdest...)
		cell := make(map[string]interface{})
		for i := 0; i < len(columns); i++ {

			switch scannerdest[i].(type) {
			case *int64:
				var val int64 = *scannerdest[i].(*int64)
				cell[columns[i]] = val
			case *float64:
				var val float64 = *scannerdest[i].(*float64)
				cell[columns[i]] = val
			case *string:
				var val string = *scannerdest[i].(*string)
				cell[columns[i]] = val
			default:
				logger.Error("其他类型的SCANER暂不支持")
				return nil,errors.New("其他类型的SCANER暂不支持")
			}
		}
		result = append(result, cell)
	}

	return result, nil
}


type IntScaner struct {
	IntVal int64
}
type FloatScaner struct {
	FloatVal float64
}
type StringScaner struct {
	StringVal string
}

func CreateScanerDest(columnName []string, scanType []reflect.Type) ([]interface{}) {
	result := make([]interface{}, 0, 10)
	for _, v := range scanType {
		switch v.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16,
			reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8,
			reflect.Uint16, reflect.Uint32, reflect.Uint64:
			var intScaner = IntScaner{}
			result = append(result, &(intScaner.IntVal))
		case reflect.Float32, reflect.Float64:
			var floatScaner = FloatScaner{}
			result = append(result, &(floatScaner.FloatVal))
		case reflect.String, reflect.Slice:
			var stringScaner = StringScaner{}
			result = append(result, &(stringScaner.StringVal))
		default:
			logger.Error("其他类型的SCANER暂不支持v.Kind()[" + v.Kind().String() + "]")
			panic(errors.New("其他类型的SCANER暂不支持v.Kind()[" + v.Kind().String() + "]"))
		}
	}
	return result
}

func EXEC_TEMPLATE(mappermodule MapperModule, method string, param interface{}) (int, error) {
	var dbAnTxInterface DbAnTxInterface
	var stmt *sql.Stmt
	var err error
	fmt.Println(mappermodule.BeginTx)
	if (mappermodule.BeginTx) {
		//事务已开启，说明已有db
		dbAnTxInterface = mappermodule.TX
	} else {
		dbAnTxInterface = gdbc.GetDB(mappermodule.GdbcName)
	}

	//加载Mapper文件信息
	var execsql, _ = getExecSql(mappermodule, method,param)

	//解析参数与Mapper映射关系
	var args []interface{}
	execsql,args,err = parseParameter(execsql,param)
	if err != nil {
		logger.Error("解析参数错误[" + err.Error() + "]")
		return 0, err
	}
	//预编译SQL
	stmt, err = dbAnTxInterface.Prepare(execsql)
	if (err != nil) {
		logger.Error("预编译sql错误错误信息为[" + err.Error() + "]")
		return 0, err
	}
	defer stmt.Close()

	//执行SQL
	result, err := stmt.Exec(args...)
	if err != nil {
		logger.Error("执行SQL错误[" + err.Error() + "]")
		return 0, err
	}
	affectcount, _ := result.RowsAffected()
	logger.Debug("执行SQL结束，影响行数[" + strconv.FormatInt(affectcount, 10) + "]")
	return int(affectcount), nil
}

